package com.fairy.sso.controller;

import java.io.IOException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.fairy.core.util.DateUtil;
import com.fairy.core.util.NetUtil;
import com.fairy.sso.annotation.FairyControllerExceptionLog;
import com.fairy.sso.cache.SSOCache;
import com.fairy.sso.config.DomainCollection;
import com.fairy.sso.config.FairyConfig;
import com.fairy.sso.core.CookieHelper;
import com.fairy.sso.core.NetHelp;
import com.fairy.sso.core.SSOConstants;
import com.fairy.sso.core.SSOHelp;
import com.fairy.sso.core.SSOResult;
import com.fairy.sso.core.Ticket;
import com.fairy.sso.entity.SSOUserEntity;
import com.fairy.sso.server.Factory;
import com.fairy.sso.server.SSOCacheFactory;
import com.fairy.sso.service.SSOService;

@Controller
public class LoginController
{
  private static Logger log = Logger.getLogger(LoginController.class);

  @Autowired(required=true)
  private FairyConfig fairyConfig;

  @Autowired(required=true)
  private SSOService<SSOResult> ssoService;

  @Autowired
  private DomainCollection domainCollection;

  @RequestMapping({"/login.do"})
  @FairyControllerExceptionLog(description="用户登录")
  public ModelAndView login(HttpServletRequest request, HttpServletResponse response, Model model, RedirectAttributes attr) { ModelAndView mav = new ModelAndView("index-bank");
    long start = System.currentTimeMillis();
    String accountNo = request.getParameter("accountNo");
    String passWord = request.getParameter("passWord");
    String codeImg = request.getParameter("codeImg");
    log.info("用户输入的验证码:" + codeImg);
    String service = request.getParameter(SSOConstants.CLIENT_URL);
    service=null==service?"":service;
    log.info("============================sso客户端URL is :service:" + service+"=====================================");
    HttpSession session = request.getSession();
    String code = (String)session.getAttribute(SSOConstants.SSO_IMG_CODE);
    log.info("session中已经保存的验证码:" + code);

    log.info("session中 code:" + code + ",页面传过来的code:" + codeImg);
    String tips = "";
    if ((code != null) && (!"".equals(code)))
    {
      if (codeImg.equalsIgnoreCase(code))
      {
        log.info("session中 code:" + code + ",页面传过来的code:" + codeImg + ",验证通过");
        session.removeAttribute(SSOConstants.SSO_IMG_CODE);
        
      
        
        String domain = NetHelp.getDomain(service);
        List<String> list = this.domainCollection.getDomainList();

        if ((domain != null) && (!"".equals(domain)) && (!list.contains(domain)))
        {
          tips = "非法的来源域名";
          mav = redirectIndex(attr, service, tips, accountNo);
        }
        else
        {
          Map<String,Object> param = getParams(request, accountNo, passWord);
          SSOResult result = null;
          try
          {
            result = (SSOResult)this.ssoService.login(param, accountNo, passWord);
            if (result != null)
            {
              String serviceCode = result.getCode();
              if ((serviceCode != null) && (serviceCode.equals("000000")))
              {
                SSOUserEntity ssoUserEntity = result.getSsoUserEntity();
                if ((ssoUserEntity != null) && (ssoUserEntity.getUserId() != null) && (!"".equals(ssoUserEntity.getUserId())))
                {
                  String userIp = NetUtil.getIpAddr(request);

                  String ticketKey = SSOHelp.getMD5TicketKey();

                  InetAddress netAddress = NetHelp.getInetAddress();
                  String localHostIp = NetHelp.getHostIp(netAddress);

                  Ticket ticket = SSOHelp.getTicket("ssoServer", localHostIp, accountNo, ssoUserEntity.getUserId(), userIp, ticketKey);
                  Factory factory = new SSOCacheFactory();
                  String cacheType = this.fairyConfig.getCacheType();
                  SSOCache cache = factory.createSSOCache(cacheType);
                  cache.set(ticketKey, ticket);
                  log.info("从缓存取ticket:" + cache.get(ticketKey).toString());

                  String domains = this.fairyConfig.getDomain();

                  CookieHelper.addCookie(response, domains, this.fairyConfig.getPath(), SSOConstants.SSO_COOKIE_KEY, ticketKey, this.fairyConfig.getMaxAge());

                  mav = jumpUrl(response, attr, mav, service, ticketKey);
                }
                else
                {
                  tips = "用户不存在";
                  log.info("^_^:" +  tips);
                  mav = redirectIndex(attr, service, tips, accountNo);
                }
              }
              else
              {
                String msgReturn = result.getMsg();
                if ((msgReturn == null) || ("".equals(msgReturn)))
                {
                  msgReturn = "serviceCode 为空!";
                }
                log.info("^_^:" +  msgReturn);
                mav = redirectIndex(attr, service, msgReturn, accountNo);
              }

            }
            else
            {
              tips = "系统出错,请联系客服或者尝试重新登陆!";
              log.info("^_^:" +  tips);
              mav = redirectIndex(attr, service, tips, accountNo);
            }

          }
          catch (Exception e)
          {
        	  e.printStackTrace();
	          tips = "系统出错,请重新登陆!";
	          log.info("^_^:" +  tips);
	          mav = redirectIndex(attr, service, tips, accountNo);
            
          }
        }

      }
      else
      {
        tips = "验证码输入错误";
        log.info("^_^:" +  tips);
        mav = redirectIndex(attr, service, tips, accountNo);
      }
    }
    long end = System.currentTimeMillis();
    log.info("<<===================登录过程执行耗时:" + (end - start) + "毫秒============================>>");
    return mav; }

  @SuppressWarnings({ "rawtypes", "unchecked" })
private Map<String, Object> getParams(HttpServletRequest request, String accountNo, String passWord)
  {
    Map param = new HashMap();
    Map dataMap = new HashMap();

    param.put("reservedField", "IM030001");
    param.put("versionNo", "1.0");
    param.put("commType", "0");
    param.put("clientIP", NetUtil.getIpAddr(request));
    param.put("channelIP", "192.168.1.18");
    param.put("securityFlag", "0");
    param.put("macCode", "a|b");
    param.put("macValue", "123|345");
    param.put("packageType", "00");
    param.put("channel", "sso");
    param.put("transTime", DateUtil.getFormatCurrentDate("yyyy-MM-dd HH:mm:ss"));
    param.put("transCode", "IM030001");
    param.put("transId", "sso");
    param.put("iCIFID", "sso");
    param.put("eCIFID", "sso");
    param.put("reqId", request.getSession().getId());
    param.put("cid", "QQ0000000");
    param.put("pcid ", "QQ7777777");

    dataMap.put("channel", "sso");
    dataMap.put("loginId", accountNo);
    dataMap.put("loginPassword", passWord);

    param.put("dataMap", dataMap);
    return param;
  }

  private ModelAndView redirectIndex(RedirectAttributes attr, String service, String tips, String accountNo)
  {
    attr.addFlashAttribute("service", service);
    attr.addFlashAttribute("tips", tips);
    attr.addFlashAttribute("accountNo", accountNo);
    ModelAndView mav = new ModelAndView("redirect:/index.do?service=" + service);
    return mav;
  }

  private ModelAndView jumpUrl(HttpServletResponse response, RedirectAttributes attr, ModelAndView mav, String service, String md5Ticket)
  {
    if (service != null)
    {
      StringBuilder url = getURL(service, md5Ticket);
      log.info("=================================登录成功=================================");
      log.info("================================="+ url.toString()+"=================================" );
      log.info("=================================登录成功,返回源站=================================" );
      try {
        response.sendRedirect(url.toString());
      } catch (IOException e) {
        e.printStackTrace();
      }

    }
    else
    {
      attr.addFlashAttribute("tips", "没有跳转上文链接");
      mav = new ModelAndView("redirect:/index.do");
    }
    return mav;
  }

  @RequestMapping({"/logout.do"})
  @FairyControllerExceptionLog(description="用户注销")
  public ModelAndView logout(HttpServletRequest request, HttpServletResponse response, Model model, RedirectAttributes attr, String ticket)
  {
    ModelAndView mav = new ModelAndView("redirect:/");

    String service = request.getParameter(SSOConstants.CLIENT_URL);
    mav = new ModelAndView("redirect:" + service);
    CookieHelper.removeCookie(request, response, SSOConstants.SSO_COOKIE_KEY);
    Factory factory = new SSOCacheFactory();
    String cacheType = this.fairyConfig.getCacheType();
    SSOCache cache = factory.createSSOCache(cacheType);
    cache.delete(ticket);

    return mav;
  }

  @RequestMapping(value={"/logout2.do"}, method={org.springframework.web.bind.annotation.RequestMethod.GET})
  @FairyControllerExceptionLog(description="用户注销")
  public ModelAndView logout2(HttpServletRequest request, HttpServletResponse response, Model model, RedirectAttributes attr, String ticket)
  {
    ModelAndView mav = new ModelAndView("jsonView");
    String ticket_1 = request.getParameter("ticket");

    System.out.println(ticket_1 + "---");
    String code = "111111";
    String msg = "注销失败";
    try
    {
      if (ticket != null)
      {
        String domain = NetHelp.getDomainOrIP(request);
        CookieHelper.removeCookie(request, response, SSOConstants.SSO_COOKIE_KEY);
        log.info(getClass().getName() + "<++++++++++++++++++++++++++++++++++" + domain + "   删除cookie成功++++++++++++++++++++++++++++++++++++>");
        Factory factory = new SSOCacheFactory();
        String cacheType = this.fairyConfig.getCacheType();
        SSOCache cache = factory.createSSOCache(cacheType);
        cache.delete(ticket);
        log.info(getClass().getName() + "<++++++++++++++++++++++++++++++++++" + domain + "   删除ticket成功++++++++++++++++++++++++++++++++++++>");
        code = "000000";
        msg = "注销成功";
      }

    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    String str = "{\"ssoMsg\":\"" + msg + "\",\"ssoCode\":\"" + code + "\"}";
    mav.addObject("JSON_DATA_VIEW", str);
    return mav;
  }

  private StringBuilder getURL(String service, String md5Ticket)
  {
    StringBuilder url = new StringBuilder();
    if(service.contains("?"))
    {
    	int index=service.indexOf("?");
    	String service_s=service.substring(0, index);
    	String service_e=service.substring(index);

        HashMap<String,String>map=new HashMap<String,String>();
        this.filterURL(service_e,map);
        String services=map.get("service_url")==null?"":map.get("service_url");
    	
    	url.append(service_s);
    	url.append("?");
    	url.append(services);

    }
    else
    {
    	url.append(service);
    	url.append("?");
    }
    
    String temp=url.toString();
    if(temp.endsWith("?"))
    {
    	url.append("ticket=").append(md5Ticket);
    }
    else
    {
        if(temp.endsWith("&"))
        {
        	url.append("ticket=").append(md5Ticket);
        }
        else
        {
        	url.append("&ticket=").append(md5Ticket);
        }
    }
    boolean ssoCrossDomain=fairyConfig.getCrossDomain();
    url.append("&ssoFlag=").append("00");
    url.append("&ssoCrossDomain=").append(ssoCrossDomain);

    return url;
  }

	private void filterURL(String urls,HashMap<String,String>map)
	{
		//String temp="";
		if(urls.endsWith("&"))
	    {
	    	int endIndex=urls.lastIndexOf("&");
	    	urls=urls.substring(0, endIndex);
	    	map.put("service_url", urls);
	    	filterURL(urls,map);
	    }
		if(urls.startsWith("&"))
	    {
	    	int startIndex=urls.indexOf("&");
	    	urls=urls.substring(startIndex+1);
	    	map.put("service_url", urls);
	    	filterURL(urls,map);
	    }
		if(urls.endsWith("?"))
	    {
	    	int endIndex=urls.lastIndexOf("?");
	    	urls=urls.substring(0, endIndex);
	    	map.put("service_url", urls);
	    	filterURL(urls,map);
	    }
		if(urls.startsWith("?"))
	    {
	    	int startIndex=urls.indexOf("?");
	    	urls=urls.substring(startIndex+1);
	    	map.put("service_url", urls);
	    	filterURL(urls,map);
	    }

	}
}